package com.stress.testing.instrumentation;

import com.stress.testing.common.matcher.ClassDescription;
import com.stress.testing.common.matcher.ClassMatcher;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.field.FieldList;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.method.MethodList;
import net.bytebuddy.description.method.ParameterDescription;
import net.bytebuddy.description.method.ParameterList;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;

import java.util.ArrayList;
import java.util.List;

public class SimpleTypeElementMatcher implements ElementMatcher<TypeDescription> {
    private ClassMatcher classMatcher;

    public SimpleTypeElementMatcher(ClassMatcher classMatcher) {
        this.classMatcher = classMatcher;
    }

    @Override
    public boolean matches(TypeDescription target) {
        ClassDescription classDescription = buildClassDescription(target);
        return this.classMatcher.match(classDescription);
    }

    private ClassDescription buildClassDescription(TypeDescription target) {
        String name = target.getActualName();
        String simpleName = target.getSimpleName();

        List<com.stress.testing.common.matcher.FieldDescription> fieldDescriptions = null;
        FieldList<FieldDescription.InDefinedShape> declaredFields = target.getDeclaredFields();
        if (declaredFields != null && declaredFields.size() > 0) {
            fieldDescriptions = new ArrayList<>(declaredFields.size());

            for (FieldDescription.InDefinedShape declaredField : declaredFields) {
                String fieldName = declaredField.getName();
                String fieldDescriptor = declaredField.getDescriptor();
                com.stress.testing.common.matcher.FieldDescription fieldDescription =
                        new com.stress.testing.common.matcher.FieldDescription(fieldName, fieldDescriptor);
                fieldDescriptions.add(fieldDescription);
            }
        }

        List<com.stress.testing.common.matcher.MethodDescription> methodDescriptions = null;
        MethodList<MethodDescription.InDefinedShape> declaredMethods = target.getDeclaredMethods();
        if (declaredMethods != null && declaredMethods.size() > 0) {
            methodDescriptions = new ArrayList<>(declaredMethods.size());

            for (MethodDescription.InDefinedShape declaredMethod : declaredMethods) {
                String methodName = declaredMethod.getName();
                String methodDescriptor = declaredMethod.getDescriptor();

                String[] paramaterType = null;
                ParameterList<ParameterDescription.InDefinedShape> parameters = declaredMethod.getParameters();
                if (parameters != null && parameters.size() > 0) {
                    paramaterType = new String[parameters.size()];
                    // TODO:参数类型解析
                    /*for (ParameterDescription.InDefinedShape parameter:parameters){

                    }*/
                }

                com.stress.testing.common.matcher.MethodDescription methodDescription =
                        new com.stress.testing.common.matcher.MethodDescription(methodName, methodDescriptor, paramaterType);
                methodDescriptions.add(methodDescription);
            }
        }

        return new ClassDescription(name, simpleName, fieldDescriptions, methodDescriptions);
    }
}
